跳到主要内容

spring cloud kubernetes踩坑:Null key for a Map not allowed in JSON

这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

背景

最近在做spring cloud kubernetes改造调研,然后在获取服务元数据的时候遇到了这个错误 Null key for a Map not allowed in JSON

项目搭建还原

项目依赖版本

  • spring cloud: 2021.0.4
  • spring cloud kubernetes:spring-cloud-starter-kubernetes-client: 2.1.4

由上面spring cloud 版本管理统一管理,都是最新版本

代码

  1. 先在Application 添加注解@EnableDiscoveryClient开启分布式客户端
@SpringBootApplication
@EnableDiscoveryClient
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
  1. 编写代码获取服务相关元数据信息
@RestController
@RequestMapping("/service/v1")
@RequiredArgsConstructor
public class ServiceController {

private final DiscoveryClient discoveryClient;

@GetMapping("/service")
public List<String> getServiceList(){
return discoveryClient.getServices();
}

@GetMapping("/instance")
public Object getInstance(String name){
List<ServiceInstance> instances = discoveryClient.getInstances(name);
return instances;
}

}

测试

然后将项目部署到k8s集群中,调用上面的接口

1. 获取服务

调用接口

http://k8s/service/v1/service

这里天自己的k8s域名

然后回发现可以正常返回服务列表

2. 获取服务元数据

我们在调通接口获取服务元数据的时候就出现了上面的报错

http://k8s/service/v1/instance?name=test-service

Null key for a Map not allowed in JSON

问题定位

然后在spring-cloud-kubernetes 中找到了类似的问题

spring-cloud-kubernetes-nullKey-bug

issues链接

大致的意思是我们在service.yaml中没有定义port的名字导致报错了。 比如原先service.yaml的是

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376

可以看到我们没有定义port的名字所以我们可能需要加一下port的名字

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
name: default-http
targetPort: 9376

name: default-http

这样就解决了这个bug,那么我其他所有没有定义port name的项目呢,不是都会报错? 所以这里其实是一个bug

源码分析

spring-cloud-kubernetes-client-code

可以看到这里在获取port name的时候没有默认值处理,所以spring cloud kubernetes 官方维护人员也说这是一个bug,并修复了他

alt text

alt text

代码是修复了,遗憾的好像还没有发版,中央仓库最新版本还是有这个bug

alt text

本地自我修复

比较好的解决方式就是在本地建立一个同包同类名的类,然后自己去修改源码

alt text